#ifndef STATSxx_PREPROCESS_PREPROCESSOR_HPP
#define STATSxx_PREPROCESS_PREPROCESSOR_HPP


// STL
#include <vector> // std::vector

// Boost
#include <boost/serialization/serialization.hpp> // boost::serialization::

// jScience
#include "jScience/linalg/Matrix.hpp" // Matrix<>


//=========================================================
// Preprocessor
//=========================================================
class Preprocessor
{

public:

    Preprocessor();
    Preprocessor(
                 const Matrix<double> &X
                 );
    ~Preprocessor();

    // INITIALIZATION
    void initialize(
                    const Matrix<double> &X
                    );

    // DATA CLEANING

    // DATA SCALING
    Vector<double> normalize_data(
                                  Vector<double> x
                                  ) const;
    Matrix<double> normalize_data(
                                  Matrix<double> X
                                  ) const;

    Vector<double> denormalize_data(
                                    Vector<double> x
                                    ) const;
    Matrix<double> denormalize_data(
                                    Matrix<double> X
                                    ) const;


    Vector<double> standardize_data(
                                    Vector<double> x
                                    ) const;
    Matrix<double> standardize_data(
                                    Matrix<double> X
                                    ) const;

    Vector<double> destandardize_data(
                                      Vector<double> x
                                      ) const;
    Matrix<double> destandardize_data(
                                      Matrix<double> X
                                      ) const;

/*
    // DATA TRANSFORMATION
    Matrix<double> decorrelate_data(const Matrix<double> &X);
    Matrix<double> whiten_data(const Matrix<double> &X);
    Matrix<double> dimred_data(const Matrix<double> &X, const double f);
*/


    // STATISTICS
    std::vector<double> min() const;

    std::vector<double> max() const;

    std::vector<double> std_dev() const;


private:

    bool                init;

    Matrix<double>      X_init;

    std::vector<double> x_min;
    std::vector<double> x_max;
    std::vector<double> x_max_minus_min;
    std::vector<double> x_mean;
    std::vector<double> x_s;


    // (Boost) SERIALIZATION
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(
                   Archive            &ar,
                   const unsigned int  version
                   )
    {
        ar & this->init;

        ar & this->X_init;

        ar & this->x_min;
        ar & this->x_max;
        ar & this->x_max_minus_min;
        ar & this->x_mean;
        ar & this->x_s;
    }
};

#include "statsxx/preprocess/Preprocessor/Preprocessor.cpp"
#include "statsxx/preprocess/Preprocessor/initialize.cpp"
#include "statsxx/preprocess/Preprocessor/normalize_data.cpp"
#include "statsxx/preprocess/Preprocessor/denormalize_data.cpp"
#include "statsxx/preprocess/Preprocessor/standardize_data.cpp"
#include "statsxx/preprocess/Preprocessor/destandardize_data.cpp"
#include "statsxx/preprocess/Preprocessor/statistics.cpp"


#endif
